package gl.java.umsp.gateway;

import gl.java.network.transport.kcp.umsp.UmspKcpGateWayServer;
import gl.java.network.transport.kcp.umsp.UmspKcpServer;
import gl.java.umsp.*;
import gl.java.umsp.event.Event;
import gl.java.umsp.event.EventSubscriber;
import gl.java.umsp.gateway.websocket.GateWayWebSocketFrameHandler;
import gl.java.umsp.websocket.UmspWebSocketService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

@Slf4j
public class UmspGateWayService  {

    private static final String KEY_GATEWAY_SERVICE_LIST = "UmspGateWayService";
    private int port;

    public UmspGateWayService(int port) {
        this.port = port;
    }


    public static void main(String[] args) throws Exception {
        if (args.length > 0) {
            GateWayServiceConfig.getDefaultConfig().setPort(Integer.parseInt(args[0]));
        }
        int port = GateWayServiceConfig.getDefaultConfig().getPort();
        final int webSocketPort = port-1;
        final int udpSocketPort = port-2;
        //开启线程启动WebSocket服务
        new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    Thread.sleep(500);
                    new UmspWebSocketService(webSocketPort
                            , "/ws", GateWayWebSocketFrameHandler.class).run();
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("stop ,gateway websocket service exception:  " + e);
                }

            }
        }.start();
        //开启线程启动udpSocket服务
        new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    Thread.sleep(1000);
                    UmspKcpGateWayServer.start(udpSocketPort);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("stop ,gateway websocket service exception:  " + e);
                }

            }
        }.start();
        //启动 Umsp 二进制协议服务
        new UmspGateWayService(port).start(GateWayServiceConfig.getDefaultConfig());

    }

    public void start(final GateWayServiceConfig config) {

        EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap(); // (2)
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class) // (3)
                    .childHandler(new ChannelInitializer<SocketChannel>() { // (4)
                        @Override
                        public void initChannel(SocketChannel ch)
                                throws Exception {
                            ch.pipeline().addLast(
                                    new UmspConnectionHandler(),
                                    new UmspMessageUnpacker(),
                                    new UmspMessagePacker(),
                                    new UmspMessageDecoder(),
                                    new GateWayMessageDispatcher()
                            );
                        }
                    }).option(ChannelOption.SO_BACKLOG, 128);

            ChannelFuture f = b.bind(port).sync(); // (7)
            f.addListener(new GenericFutureListener<Future<? super Void>>() {

                @Override
                public void operationComplete(Future<? super Void> future)
                        throws Exception {
                    log.info("===============================================");
                    log.info("==   GateWayService is Running at port" + port + "  ==");
                    log.info("===============================================");
                    EventSubscriber.registerAsyncSubscriberCallBack(InnerServiceEventHandler.getInstance(), Event.CHANNEL_MATCH_EVENT_RESULT, Event.ERR);
                }
            });
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error(e.getCause()+"");
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
            log.info("=====================================");
            log.info("======= Stop GateWay MessageQueueService at :" + new Date() + "=====");
            log.info("=====================================");
            stop();
        }

    }
    public void stop() {
        log.error("GateWayService System.exit(0),please check the log");
        System.exit(0);
    }
}
